#ifndef __M_BUFFER_H__
#define __M_BUFFER_H__

#include <algorithm>
#include "util.hpp"
#include "logger.hpp"


#define DEFAULT_BUFFER_SIZE (100*1024*1024)
#define INCREMENT_BUFFER_SIZE (80*1024*1024)

class Buffer
{
private:
    vector<char> _buffer;
    size_t reader_idx;
    size_t writer_idx;
    void moveWriter(size_t len)
    {
        assert(len+writer_idx<=_buffer.size());
        writer_idx+=len;
    }
    void ensureEnoughSize(size_t len)
    {
        if(len<writeAbleSize())return;
        size_t new_size=0;
        if(_buffer.size()<DEFAULT_BUFFER_SIZE)
        {
            new_size = _buffer.size()*2;
        }else
        {
            new_size =_buffer.size()+INCREMENT_BUFFER_SIZE;
        }
        _buffer.resize(new_size);
    }
public:
    Buffer():_buffer(DEFAULT_BUFFER_SIZE),reader_idx(0),writer_idx(0){}
    
    void push(const char* data,size_t len){
        ensureEnoughSize(len);

        copy(data,data+len,&_buffer[writer_idx]);
        moveWriter(len);
    }

    const char* begin()
    {
        return &_buffer[reader_idx];
    }

    size_t readAbleSize()
    {
        return writer_idx-reader_idx;
    }
    size_t writeAbleSize()
    {
        return _buffer.size()-writer_idx;
    }
    void moveReader(size_t len)
    {
        assert(len<=readAbleSize());
        reader_idx+=len;
    }

    void reset()
    {
        writer_idx=0;
        reader_idx=0;
    }

    void swap(Buffer& buffer)
    {
        _buffer.swap(buffer._buffer);
        std::swap(reader_idx,buffer.reader_idx);
        std::swap(writer_idx,buffer.writer_idx);

    }

    bool empty()
    {
        return reader_idx==writer_idx;
    }
};



#endif